package com.product.android.utils;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;

import com.common.android.utils.AppUtils;
import com.common.android.utils.Base64EncoderUtils;
import com.common.android.utils.FileUtils;
import com.common.android.utils.MD5ArithmeticUtils;
import com.common.android.utils.SdCardUtils;
import com.common.android.utils.ToastUtils;
import com.nd.android.u.allcommon.R;
import com.product.android.business.ApplicationVariable;
import com.product.android.business.config.Configuration;

/**
 * 对SD卡文件的管理
 */
public class FileHelper {
    private static final String BASE_PATH=Configuration.PATH+"/";
	public static final String UPLOAD="upload";
	public static final String OFFLINEFILEDIR = "ofile";
	public static final String AUDIO = "audio";
	public static final String AUDIO_PRE = "androidVoice";
	public static final String IMAGE = "image";
	public static final String CHAT = "chat";
	public static final int DEFAULT_COMPRESS_QUALITY = 80;
	public static final String THUMBNAIL_NAME="_thumb";
	public static final String VIDEO="video";

	// 内存类型
	public static final int TYPE_PHONE_MEMORY = 0x100;
	// SD卡
	public static final int TYPE_SD_MEMORY = 0x101;
	// 扩展卡
	public static final int TYPE_EXSD_MEMORY = 0x102;
	
	
	/**
	 * 获取99u的应用程序所在路径
	 * <br>Created 2014-8-25 下午6:07:53
	 * @param filepath 文件路径
	 * @return 文件路径
	 * @throws IOException
	 * @author       huangyx
	 */
    public static File getBasePath(String filepath) throws IOException {
    	String path = BASE_PATH;    
    	File basePath = null;
    	String name = ApplicationVariable.INSTANCE.getUserName();
    	if(!TextUtils.isEmpty(name)){
    		long uid = ApplicationVariable.INSTANCE.getOapUid();
    		path += name.trim() + "(" + uid + ")" + "/" + filepath;    
    	} else {
    		path += filepath;
    	}
    	if(SdCardUtils.isSdCardExist()) {
            int version_sdk = 0;
            try {
                version_sdk = Integer.valueOf(android.os.Build.VERSION.SDK);
            } catch (NumberFormatException e) {
                version_sdk = 0;
            }

            if (Configuration.IS_EXTERNAL_FILE_DIR && version_sdk >= Build.VERSION_CODES.FROYO) {
    			//见CommonConfig.IS_EXTERNAL_FILE_DIR
    			basePath = ApplicationVariable.INSTANCE.applicationContext.getExternalFilesDir(path);	
    		}
    		if (basePath == null){
    			basePath = new File(Environment.getExternalStorageDirectory(),	path);
    		}
    	} else {
    		basePath = new File(ApplicationVariable.INSTANCE.applicationContext.getCacheDir(),path);
    	}

        // 如果文件是属于不可读写的，则抛异常。
        if (!basePath.canWrite() || !basePath.canRead()) {
            ToastUtils.display("The file cannnot be read or write!");
            Log.e("HYK",String.format("%s cannnot be read or write!", basePath.toString()));
            throw new IOException(String.format("%s cannot be writed/readed!", basePath.toString()));
        }

        //如果不存在并且创建失败，则抛异常
    	if (!basePath.exists()){
    		if (!basePath.mkdirs()){
                ToastUtils.display("The file cannnot be read or write!");
                Log.e("HYK",String.format("%s cannot be created!", basePath.toString()));
        		throw new IOException(String.format("%s cannot be created!", basePath.toString()));
    		}
    	}
    	if (!basePath.isDirectory()){
            ToastUtils.display("The file is not a directory!");
            Log.e("HYK",String.format("%s is not a directory!", basePath.toString()));
    		throw new IOException(String.format("%s is not a directory!", basePath.toString()));
    	}
		return basePath;
    }
    
    public static String getAudioFileName(String url){
    	String fileName = AUDIO_PRE+MD5ArithmeticUtils.getMd5(url)+".amr";
    	return fileName;
    }
    
    /**
     * 获取视频文件名
     * <br>Created 2014-5-9 上午10:42:17
     * @param url 文件的网络地址
     * @param extName 文件的扩展名
     * @return 视频文件名
     * @author       cb
    */
    public static String getVedioFileName(String url,String extName){
    	String fileName = VIDEO + MD5ArithmeticUtils.getMd5(url) + "." + extName;
    	return fileName;
    }
    
    /**
     * 获取图片文件名
     * <br>Created 2014-8-25 下午8:33:32
     * @param pre 图片文件名前缀
     * @return 图片文件名
     * @author       huangyx
     */
    private static String getImageFileName(String pre){
    	return pre + System.currentTimeMillis() + ".jpg";
    }
    
    /**
     * 获取下载文件名
     * <br>Created 2014-8-25 下午8:34:38
     * @param filename 文件名
     * @param url 源URL
     * @return 文件名
     * @author       huangyx
     */
    private static String getDownloadFileName(String filename, String url){
    	String prefilename = "";
		String suffilename = "";
		if (filename.length() > 0) {
			int i = filename.lastIndexOf('.');
			if ((i > -1) && (i < (filename.length() - 1))) {
				prefilename = filename.substring(0, i);
				suffilename = filename.substring(i);
			}
		}
		String md5 = MD5ArithmeticUtils.getMd5(url);
		if (md5.length() > 8){
			md5 = md5.substring(0, 8);
		}
		String genename = prefilename + "_" + md5 + suffilename;	
		return genename;
    }
    
    /**
     * 获取默认音频文件
     * <br>Created 2014-8-25 下午8:36:48
     * @param url 源URL
     * @return 音频文件
     * @throws IOException
     * @author       huangyx
     */
    public static File getDefaultAudioFile(String url) throws IOException{
    	return new File(getBasePath(AUDIO), getAudioFileName(url));
    }
    
    /**
     * 获取默认图片文件
     * <br>Created 2014-8-25 下午8:37:48
     * @param pre 源URL
     * @return 图片文件
     * @throws IOException
     * @author       huangyx
     */
    public static File getDefaultImageFile(String pre) throws IOException{
    	return new File(getBasePath(IMAGE),getImageFileName(pre));
    }
    
    /**
     * 获取默认的视频文件
     * <br>Created 2014-5-9 上午10:42:29
     * @param url 源URL
     * @param extName 扩展名
     * @return 视频文件
     * @throws IOException
     * @author       cb
    */
    public static File getDefaultVideoFile(String url,String extName) throws IOException{
    	return new File(getBasePath(VIDEO),getVedioFileName(url,extName));
    }
    
    /**
     * 获取默认的下载文件名
     * <br>Created 2014-5-9 上午10:42:29
     * @param filename 文件名
     * @param url 源URL
     * @return 下载文件名
     * @throws IOException
     * @author       cb
    */
    public static File getDefaultDownloadFile(String filename,String url) throws IOException{
    	return new File(getBasePath(OFFLINEFILEDIR), getDownloadFileName(filename, url));
    }
    
    /**
     * 获取chat文件路径
     * <br>Created 2014-8-25 下午8:39:55
     * @return chat文件路径
     * @throws IOException
     * @author       huangyx
     */
    public static File getBasePathCHAT() throws IOException{
    	return getBasePath(CHAT);
    }
    
    /**
     * 保存图片
     * <br>Created 2014-8-25 下午8:41:54
     * @param file 文件名
     * @param bitmap 图片
     * @throws IOException
     * @author       huangyx
     */
    public static void saveBitmap(File file , Bitmap bitmap) throws IOException {
		if(bitmap==null) return;
        FileOutputStream fOut = null;
        try {
            fOut = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        bitmap.compress(Bitmap.CompressFormat.JPEG, DEFAULT_COMPRESS_QUALITY, fOut);
        try {
        	if (fOut != null) {
        		fOut.flush();
        		fOut.close();
        	}
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
   
    //微博服务器支持的图片格式
    public static String[] exts = {"jpg","jpeg","png","gif"};
    
    /**
     * 判定要上传的图片格式是不是微博服务器允许的
     * <br>Created 2014-4-18下午1:51:36
     * @param sFileName 文件名
     * @return 上传的图片格式是微博服务器允许的返回true，否则返回false
     * @author       huangszh
     */
    public static boolean isWeiboSupportImage(String sFileName){
    	return FileUtils.isSupportExtFile(sFileName, exts);
    }
    
    /**
     * 创建nomedia文件
     * <br>Created 2014-8-25 下午8:54:00
     * @param sbPath 文件路径
     * @author       huangyx
     */
	public static void createNomedia(StringBuilder sbPath) {
		File file = new File(sbPath.toString() + ".nomedia");
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 得到文件下载路径
	 * <br>Created 2014-8-25 下午8:53:32
	 * @return 文件下载路径
	 * @author       huangyx
	 */
	public  static String  getDownloadFilePath() {
		return BASE_PATH+ "download/";
	}
	
	/**
	 * 根据路径返回文件
	 * 
	 * @throws IOException
	 */
	public static File creatFileByPath(String fileName) throws IOException {
		File file = new File(BASE_PATH + fileName);
		return file;
	}
	
	 /**
     * 获取image文件的路径
     * <br>Created 2014-8-25 下午8:57:51
     * @return
     * @throws IOException
     * @author       huangyx
     */
    public static File getBasePathIMAGE() throws IOException{
        return getBasePath("image");
    }
	
    /**
     * 获取Thumb文件名
     * <br>Created 2014-8-25 下午8:58:34
     * @param thumbName 文件路径
     * @return Thumb文件名
     * @author       huangyx
     */
    public static String getThumbnailName(String thumbName){
    	String filename = FileUtils.getFilename(thumbName);
    	//记录传入的文件名是否包含路径
		int last = filename.lastIndexOf(".");
		if (last > 0) {
			filename = filename.substring(0,last) + THUMBNAIL_NAME + filename.substring(last);
		} else {
			filename += THUMBNAIL_NAME;
		}
		return filename;
    }
    
    /**
     * 对文件二进制内容进行BASE64Encode
     * <br>Created 2014-2-18下午6:40:20
     * @param file 文件
     * @return 文件二进制内容进行BASE64Encode结果
     * @author       PanYun
     */
	public static String tansferToByteArrayBASE64Encode(File file) {
		if (!file.exists()) {
			return null;
		}

		try {
			FileInputStream stream = new FileInputStream(file);
			ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
			byte[] b = new byte[1000];
			int n;
			while ((n = stream.read(b)) != -1)
				out.write(b, 0, n);
			stream.close();
			out.close();
			return Base64EncoderUtils.encode(out.toByteArray()).replaceAll("\\n", "");
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * 打开文件浏览界面前判断可读目录
	 * <br>Created 2014-1-27上午12:16:17
	 * @param context 上下文
	 * @return 可读目录
	 * @author       HuangYK
	 */
	@SuppressLint({ "UseSparseArrays", "InlinedApi" })
    public static HashMap<Integer, String> getStorageDirectories(Context context) {
		// 判断是否root
		HashMap<Integer, String> pathList= new HashMap<Integer, String>(); 
		pathList.put(TYPE_PHONE_MEMORY, "/");
		// 如果SD卡不存在则直接返回
		if (!SdCardUtils.isSdCardExist()) {
			return pathList;
		}
		// 取SD卡路径并且添加到列表中
		String sdcardPath = SdCardUtils.getSdCardPath();
		pathList.put(TYPE_SD_MEMORY, sdcardPath);
		
		try {
			// 如果SDK版本大于等于11，则可能会有外置存储卡，通过反射获取
			if (Build.VERSION.SDK_INT >= 11) {
				StorageManager sm = (StorageManager) context
						.getSystemService(Context.STORAGE_SERVICE);
				String[] volumePaths = (String[]) sm.getClass()
						.getMethod("getVolumePaths").invoke(sm);
				if (null != volumePaths) {
					int key = TYPE_EXSD_MEMORY;
					for (int i = 0; i < volumePaths.length; i++) {
						// 路径为空，跳下一个
						if (null == volumePaths[i]) {
							continue;
						}
						File dir = new File(volumePaths[i]);
						// 路径不可读，则跳到下一个
						if (!dir.canRead()) {
							continue;
						}
						// 如果路径不等于SD卡，则添加
						if (!sdcardPath.equals(volumePaths[i])) {
							while (true) {
								if (!pathList.containsKey(key)) {
									pathList.put(key, volumePaths[i]);
									break;
								} else {
									key++;
									continue;
								}
							}
						}
					}
					return pathList;
				}
			}
			return pathList;
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return pathList;
	}
	
	/**
	 * 将某些系统文件设置为可读写(比如/data)
	 * <br>Created 2014-1-26下午10:41:56
	 * @param path 文件路径
	 * @return 可读写返回true，否则返回false
	 * @author       HuangYK
	 */
	public static boolean upgradeRootPermission(String path) {
		if (!AppUtils.isRoot()) {
			return false;
		}
		Process process = null;
		DataOutputStream os = null;
		try {
			String cmd = "chmod 777 " + path;
			process = Runtime.getRuntime().exec("su"); // 切换到root帐号
			os = new DataOutputStream(process.getOutputStream());
			os.writeBytes(cmd + "\n");
			os.writeBytes("exit\n");
			os.flush();
			process.waitFor();
		} catch (Exception e) {
			return false;
		} finally {
			try {
				if (os != null) {
					os.close();
				}
				process.destroy();
			} catch (Exception e) {
			}
		}
		return true;
	}
	
	/**
     * 获取临时存放目录
     * <br>Created 2014-8-22 上午9:17:01
     * @param sbPath 返回路径
     * @return 获取成功返回0
     * @author       huangyx       
     */
    public static int getTempPath(StringBuilder sbPath) {
        return getNotePath(Configuration.TempDir, sbPath);
    }
    
    /**
     * 获取临时存放目录
     * <br>Created 2014-8-22 上午9:15:01 
     * @param dir 目录类型
     * @param sbPath 返回获取对路径
     * @return 获取成功返回0
     * @author       huangyx             
     */
    private static int getNotePath(String dir, StringBuilder sbPath) {
        int ireturn = R.string.sdcard_not_found;
        try {
            sbPath.delete(0, sbPath.length());
            if (Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED)) {
                String sdcardpath = Environment.getExternalStorageDirectory()
                        .getAbsolutePath();
                sbPath.append(sdcardpath).append(Configuration.separatorChar)
                        .append(Configuration.PATH);

                File noteDir = new File(sbPath.toString());
                if (!noteDir.exists()) {
                    noteDir.mkdir();
                }
                sbPath.append(Configuration.separatorChar).append(dir);
                sbPath.append(Configuration.separatorChar);
                noteDir = new File(sbPath.toString());
                if (!noteDir.exists()) {
                    noteDir.mkdir();
                    FileHelper.createNomedia(sbPath);
                }
                ireturn = 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ireturn;
    }
}